Zynq

您所在的位置:网站首页 platform cable usb驱动安装 Zynq

Zynq

2023-09-22 15:11| 来源: 网络整理| 查看: 265

1、功能介绍

XVC—Xilinx Virtual Cable,是Xilinx推出的基于TCP/IP协议的远程调试方法,可用于Xilinx FPGA的远程下载。其作用是可替代目前常用的Xilinx官方下载器Platform Cable USB Ⅱ,通过网线即可实现FPGA程序的加载和调试,简要结构如下图所示:

ZYNQ通过网线实现与调试机之间的数据传输,ARM处理器通过AXI 转JTAG IP核,将文件通过V7的JTAG口与V7进行交互,实现V7的程序下载与调试,简要结构如下图所示。

2、硬件设计示意图

3、ZYNQ VIVADO功能设计

(1)、将axi转JTAG IP核添加在ZYNQ工程。具体操作:点击Tools,进入Project Settings ,进入IP,找到Repository Manager,将附件中的IP核添加到工程中;

(2)、在BD文件中,添加AXI-Lite to JTAG 核,另增加一个AXI GPIO核,该4T245的使能信号拉到软件顶层,方便在顶层APP进行XVC功能选用。

(3)、由于ZYNQ工作时会有一个默认的高电平,V7的JTAG信号直接拉到ZYNQ时,ZYNQ会将V7的JTAG拉死,造成Xilinx仿真器使用时无法扫到FPGA,因而ZYNQ的JTAG输出信号需要进行相应处理。

4、软件设计 修改内核uio驱动文件“uio_pdrv_genirq.c”:

修改内核配置文件打开“CONFIG_OF”并且编译配置文件,再使用“make menuconfig”命令,进入内核配置菜单,关闭“cpu idle PM support”选项,使能“userspace I/O platform driver with generic IRQ handling”;修改设备树文件,更改uio驱动:

将xvcServer.c编译后生成的可执行文件传入板卡。注意:xvcServer.c中打开的是“/dev/uio0文件,如有冲突需修改设备树或者xvcServer.c文件。代码如下: /* This work, "xvcServer.c", is a derivative of "xvcd.c" (https://github.com/tmbinc/xvcd) * by tmbinc, used under CC0 1.0 Universal (http://creativecommons.org/publicdomain/zero/1.0/). * "xvcServer.c" is licensed under CC0 1.0 Universal (http://creativecommons.org/publicdomain/zero/1.0/) * by Avnet and is used by Xilinx for XAPP1251. * * Description : XAPP1251 Xilinx Virtual Cable Server for Linux */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define MAP_SIZE 0x10000 typedef struct { uint32_t length_offset; uint32_t tms_offset; uint32_t tdi_offset; uint32_t tdo_offset; uint32_t ctrl_offset; } jtag_t; static int verbose = 0; static int sread(int fd, void *target, int len) { unsigned char *t = target; while (len) { int r = read(fd, t, len); if (r sizeof(buffer)) { fprintf(stderr, "buffer size exceeded\n"); return 1; } if (sread(fd, buffer, nr_bytes * 2) != 1) { fprintf(stderr, "reading data failed\n"); return 1; } memset(result, 0, nr_bytes); if (verbose) { printf("\tNumber of Bits : %d\n", len); printf("\tNumber of Bytes : %d \n", nr_bytes); printf("\n"); } int bytesLeft = nr_bytes; int bitsLeft = len; int byteIndex = 0; int tdi, tms, tdo; while (bytesLeft > 0) { tms = 0; tdi = 0; tdo = 0; if (bytesLeft >= 4) { memcpy(&tms, &buffer[byteIndex], 4); memcpy(&tdi, &buffer[byteIndex + nr_bytes], 4); ptr->length_offset = 32; ptr->tms_offset = tms; ptr->tdi_offset = tdi; ptr->ctrl_offset = 0x01; /* Switch this to interrupt in next revision */ while (ptr->ctrl_offset) { } tdo = ptr->tdo_offset; memcpy(&result[byteIndex], &tdo, 4); bytesLeft -= 4; bitsLeft -= 32; byteIndex += 4; if (verbose) { printf("LEN : 0x%08x\n", 32); printf("TMS : 0x%08x\n", tms); printf("TDI : 0x%08x\n", tdi); printf("TDO : 0x%08x\n", tdo); } } else { memcpy(&tms, &buffer[byteIndex], bytesLeft); memcpy(&tdi, &buffer[byteIndex + nr_bytes], bytesLeft); ptr->length_offset = bitsLeft; ptr->tms_offset = tms; ptr->tdi_offset = tdi; ptr->ctrl_offset = 0x01; /* Switch this to interrupt in next revision */ while (ptr->ctrl_offset) { } tdo = ptr->tdo_offset; memcpy(&result[byteIndex], &tdo, bytesLeft); if (verbose) { printf("LEN : 0x%08x\n", 32); printf("TMS : 0x%08x\n", tms); printf("TDI : 0x%08x\n", tdi); printf("TDO : 0x%08x\n", tdo); } break; } } if (write(fd, result, nr_bytes) != nr_bytes) { perror("write"); return 1; } } while (1); /* Note: Need to fix JTAG state updates, until then no exit is allowed */ return 0; } int main(int argc, char **argv) { int i; int s; int c; int fd_uio; struct sockaddr_in address; opterr = 0; while ((c = getopt(argc, argv, "v")) != -1) switch (c) { case 'v': verbose = 1; break; case '?': fprintf(stderr, "usage: %s [-v]\n", *argv); return 1; } fd_uio = open("/dev/uio0", O_RDWR ); if (fd_uio < 1) { fprintf(stderr,"Failed to Open UIO Device\n"); return -1; } s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) { perror("socket"); return 1; } volatile jtag_t* ptr = (volatile jtag_t*) mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd_uio, 0); if (ptr == MAP_FAILED) fprintf(stderr, "MMAP Failed\n"); close(fd_uio); i = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof i); address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(2542); address.sin_family = AF_INET; if (bind(s, (struct sockaddr*) &address, sizeof(address)) < 0) { perror("bind"); return 1; } if (listen(s, 5) < 0) { perror("listen"); return 1; } fd_set conn; int maxfd = 0; FD_ZERO(&conn); FD_SET(s, &conn); maxfd = s; while (1) { fd_set read = conn, except = conn; int fd; if (select(maxfd + 1, &read, 0, &except, 0) < 0) { perror("select"); break; } for (fd = 0; fd maxfd) { maxfd = newfd; } FD_SET(newfd, &conn); } } else if (handle_data(fd,ptr)) { if (verbose) printf("connection closed - fd %d\n", fd); close(fd); FD_CLR(fd, &conn); } } else if (FD_ISSET(fd, &except)) { if (verbose) printf("connection aborted - fd %d\n", fd); close(fd); FD_CLR(fd, &conn); if (fd == s) break; } } } munmap((void *) ptr, MAP_SIZE); return 0; }

5、使用方法

如图所示准备环境:

模块上电、系统启动完成后,设置模块及调试机网络地址(同网段,不同地址),后台运行xvcServer程序(ZYNQ APP)(./xvcServer.elf &);

如果模块设计兼容两种调试方式(JTAG/XVC),需要使能XVC,一般为GPIO拉高或者拉低;

在调试机打开vivado2018.3软件(验证时低版本可能会有问题),点击“Open Hardware Manager”; 

在tcl console 命令窗口中输入 “connect_hw_server”,或者点击open target->auto connect;

右键localhost,选择Add Xilinx Virtual Cable(xvc),填写板子上的ZYNQ IP,即可。

可以看到通过将ZYNQ作为JTAG使用,通过网络就连上了模块上面的V7。

6、不足

XVC的性能受处理器影响,在处理器的资源使用过多时,可能会影响XVC的性能。

更多参考xilinx官方材料:

xapp1251.zip

xapp1251-xvc-zynq-petalinux.pdf



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3